# auto load
@tool
extends Node

## 库存管理器 （Auto Load）
#class_name InventoryManager


const _ITEMS_PATH = "res://test/data/all_items.tres"
const _BAG_PATH = "res://test/data/bag.tres"
const _CHESTS_DIR = "res://test/data/chest/"
var _items_dict: Dictionary = {}
var bag: Inventory      ## 玩家背包


func _enter_tree() -> void:
    var items = ResourceLoader.load(_ITEMS_PATH) as AllItems
    for item in items.list:
        _items_dict[item.id] = item
    bag = ResourceLoader.load(_BAG_PATH) as Inventory

    # print("InventoryManager, all items: ", _items_dict)
    

## 获取仓库[param ivt]中的给定[param id]的物品的总数量
func get_item_total(ivt: Inventory, id: int) -> int:
    var count := 0
    for item in ivt.list:
        if item == null or item.id != id: continue
        count += item.count
    return count


## 获取给定[param id]的物品
func get_item(id: int) -> Item:
    return _items_dict.get(id, null)


## 在仓库之间交换物品
func swap_items(local_ivt: Inventory, local_index: int, accept_ivt: Inventory, accept_index: int) -> void:
    var temp = accept_ivt.list[accept_index]
    accept_ivt.list[accept_index] = local_ivt.list[local_index]
    local_ivt.list[local_index] = temp
    
    local_ivt.items_updated.emit()
    accept_ivt.items_updated.emit()
 

## 获取仓库[param ivt]中所有物品的总数量
func get_all_items_total(ivt: Inventory) -> int:
    var count := 0
    for item in ivt.list:
        if item == null: continue
        count += item.count
    return count


## 获取包含所有物品[Item]的列表
func get_all_items() -> Array:
    return _items_dict.values()


## 向指定的仓库[param ivt]中添加[param count]数量的指定[param id]的物品。通过判断返回的值来确定是否将物品全部添加进仓库[color=green]（返回值==0, 表示全部添加）[/color][br]
## 发送[signal Inventory.items_updated]信号[br]
## [b][color=red]Note: count >= 1[/color][/b]
## [codeblock]
## var count := InventoryManager.add_items(InventoryManager.bag, 0, 100)
## if count:
##     print("背包已满，还有%d个物品未被添加" % count)
## else:
##     print("全部添加完毕")
## [/codeblock]
func add_items(ivt: Inventory, id: int, count: int) -> int:
    if count <= 0: return 0
    var item: Item = _items_dict.get(id, null)
    if item == null: return -1
    # 物品不可堆叠
    if not item.can_stacked:
        for i in range(ivt.capacity):
            if count <= 0: break
            if ivt.list[i] != null: continue
            var ivt_item := InventoryItem.new()
            ivt_item.setup(id, 1)
            ivt.list[i] = ivt_item
            count -= 1
    # 物品可堆叠
    else:
        # 在库存查找已存在的要添加的物品，并修改数量
        for i in range(ivt.capacity):
            if count <= 0: break
            if ivt.list[i] == null or ivt.list[i].id != id: continue
            var c := count + ivt.list[i].count
            if c <= item.max_stack_count:
                ivt.list[i].count = c
                count = 0
                break
            ivt.list[i].count = item.max_stack_count
            count = c - item.max_stack_count
        
        # 库存中已有的要添加的物品都被遍历操作后，要添加的物品仍没被添加完，就查找库存中的空闲位置，在其上添加
        if count > 0:
            for i in range(ivt.capacity):
                if count <= 0: break
                if ivt.list[i] != null: continue
                if count <= item.max_stack_count:
                    var ivt_item := InventoryItem.new()
                    ivt_item.setup(id, count)
                    ivt.list[i] = ivt_item
                    count = 0
                    break
                else:
                    var ivt_item := InventoryItem.new()
                    ivt_item.setup(id, item.max_stack_count)
                    ivt.list[i] = ivt_item
                    count -= item.max_stack_count
    
    ivt.items_updated.emit()   
    return count


## 向仓库[param ivt]中指定的位置[param index]添加[param count]数量的指定[param id]的物品。通过判断返回的值来确定是否将物品全部添加进仓库[color=green]（返回值==0, 表示全部添加）[/color][br]
## [param index] 上没有物品或物品id与被添加物品[param id]相同且可堆叠时才可以被添加[br]
## 发送[signal Inventory.items_updated]信号[br]
## [b][color=red]Note: count >= 1[/color][/b]
func add_items_by_index(ivt: Inventory, id: int, count: int, index: int) -> int:
    if count <= 0: return 0
    var item := _items_dict[id] as Item
    # index 位置上没有物品
    if ivt.list[index] == null:
        var ivt_item := InventoryItem.new()
        ivt_item.id = id
        if item.max_stack_count <= count:
            ivt_item.count = item.max_stack_count
            count -= item.max_stack_count
        else:
            ivt_item.count = count
            count = 0
    # index 位置上有物品
    else:
        # 同一种物品
        if id == ivt.list[index].id:
            if item.can_stacked:
                var c = count + ivt.list[index].count
                if c <= item.max_stack_count:
                    ivt.list[index].count = c
                    count = 0
                else:
                    ivt.list[index].count = item.max_stack_count
                    count = c - item.max_stack_count

    ivt.items_updated.emit()  
    return count


## 从仓库[param ivt]中删除在[param index]位置上的[param count]数量的物品[br]
## 发送[signal Inventory.items_updated]信号
func remove_items_by_index(ivt: Inventory, index: int, count: int = 1) -> void:
    if count <= 0: return
    if ivt.list[index] == null: return
    var item := ivt.list[index]
    item.count -= count
    if item.count <= 0:
        ivt.list[index] = null
    
    ivt.items_updated.emit()
    

## 从仓库[param ivt]中删除指定[param id]的[param count]数量的物品[br]
## 发送[signal Inventory.items_updated]信号
func remove_items_by_id(ivt: Inventory, id: int, count: int = 1) -> void:
    if count <= 0: return    
    var item: Item = _items_dict.get(id, null)
    if item == null: return
    for i in range(ivt.capacity):
        if count <= 0: break
        if ivt.list[i] == null or ivt.list[i].id != id: continue
        # 物品不可堆叠
        if not item.can_stacked:
            ivt.list[i] = null
            count -= 1
        # 物品可堆叠
        else:
            if ivt.list[i].count <= count:
                count -= ivt.list[i].count
                ivt.list[i] = null
            else:
                ivt.list[i].count -= count
                count = 0

    ivt.items_updated.emit()


## 整理仓库[param ivt]，将库存中的物品重新依次存放 [br]
## [color=yellow][param way] 排序物品的方式 (未实现)[/color]
func organize_inventory(ivt: Inventory, _way: int = 0) -> void:
    ivt.list.sort_custom(
        func(a, _b):
            if a != null:
                return true
            else:
                return false
    )
    ivt.items_updated.emit()


## 清空仓库[param ivt]
func clear_inventory(ivt: Inventory) -> void:
    ivt.list.fill(null)
    ivt.items_updated.emit()


## 保存仓库[param ivt]
func  save_inventory(ivt: Inventory, ivt_name: String = "") -> void:
    if ivt == null: return
    var path := "%s%s.tres" % [_CHESTS_DIR, ivt_name] if ivt.resource_path == "" else ivt.resource_path
    ivt.resource_path = path
    ResourceSaver.save(ivt, path)


## 删除仓库[param ivt]的本地数据
func deleteInventory(ivt: Inventory) -> void:
    print("resource_path: ", ivt.resource_path)
    if ivt == null or ivt.resource_path == "": return
    DirAccess.remove_absolute(ivt.resource_path)
